﻿using Nop.Admin.Extensions;
using Nop.Core;
using Nop.Core.Caching;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Media;
using Nop.Plugin.Widgets.Carousel.Domain;
using Nop.Plugin.Widgets.Carousel.Models;
using Nop.Plugin.Widgets.Carousel.Services;
using Nop.Services.Catalog;
using Nop.Services.Directory;
using Nop.Services.Localization;
using Nop.Services.Media;
using Nop.Services.Security;
using Nop.Services.Stores;
using Nop.Services.Tax;
using Nop.Services.Vendors;
using Nop.Web.Extensions;
using Nop.Web.Framework;
using Nop.Web.Framework.Controllers;
using Nop.Web.Framework.Kendoui;
using Nop.Web.Framework.Mvc;
using Nop.Web.Models.Catalog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

namespace Nop.Plugin.Widgets.Carousel.Controllers
{
    public class WidgetsCarouselController : BasePluginController
    {
        #region Fields
        private readonly ICarouselService _carouselService;
        private readonly IWorkContext _workContext;
        private readonly IStoreContext _storeContext;
        private readonly IStoreService _storeService;
        private readonly IPictureService _pictureService;
        
        private readonly ISpecificationAttributeService _specificationAttributeService;
        private readonly IPriceCalculationService _priceCalculationService;
        private readonly IPriceFormatter _priceFormatter;
        private readonly IWebHelper _webHelper;
        private readonly MediaSettings _mediaSettings;
        private readonly CatalogSettings _catalogSettings;
        private readonly ITaxService _taxService;
        private readonly ICurrencyService _currencyService;

        //private readonly ISettingService _settingService;
        private readonly ICacheManager _cacheManager;

        //private readonly ILanguageService _languageService;
        //private readonly ILocalizedEntityService _localizedEntityService;
        private readonly ILocalizationService _localizationService;
        private readonly IPermissionService _permissionService;
        private readonly ICategoryService _categoryService;
        private readonly IManufacturerService _manufacturerService;
        private readonly IVendorService _vendorService;
        private readonly IProductService _productService;
        #endregion

        #region crt
        public WidgetsCarouselController(ICarouselService carouselService,
            IWorkContext workContext,
            IStoreContext storeContext,
            IStoreService storeService,
            IPictureService pictureService,
            //ISettingService settingService,
            ICacheManager cacheManager,
            //ILanguageService languageService,
            //ILocalizedEntityService localizedEntityService,
            ILocalizationService localizationService,
            IPermissionService permissionService,
            ICategoryService categoryService,
            IManufacturerService manufacturerService,
            IVendorService vendorService, IProductService productService,
            IPriceCalculationService priceCalculationService,
            IPriceFormatter priceFormatter,
            IWebHelper webHelper, 
            ISpecificationAttributeService specificationAttributeService,
            MediaSettings mediaSettings,
            CatalogSettings catalogSettings,
            ITaxService taxService, 
            ICurrencyService currencyService
            )
        {
            this._carouselService = carouselService;
            this._workContext = workContext;
            this._storeContext = storeContext;
            this._storeService = storeService;
            this._pictureService = pictureService;
            //this._settingService = settingService;
            this._cacheManager = cacheManager;
            //this._languageService = languageService;
            //this._localizedEntityService = localizedEntityService;
            this._localizationService = localizationService;
            this._permissionService = permissionService;
            this._categoryService = categoryService;
            this._manufacturerService = manufacturerService;
            this._vendorService = vendorService;
            this._productService = productService;
            this._priceCalculationService = priceCalculationService;
            this._priceFormatter = priceFormatter;
            this._webHelper = webHelper;
            this._specificationAttributeService = specificationAttributeService;
            this._mediaSettings = mediaSettings;
            this._catalogSettings = catalogSettings;
            this._taxService = taxService;
            this._currencyService = currencyService;
        }
        #endregion

        #region Utilities

        [NonAction]
        protected CarouselModel PrepareCarouselModel(CarouselObject carousel)
        {

            var carouselModel = new CarouselModel()
            {
                Id = carousel.Id,
                Name = carousel.Name,
                WidgetZone = carousel.WidgetZone,
                Published = carousel.Published,
                DisplayOrder = carousel.DisplayOrder,
                CustomProductBox = carousel.CustomProductBox,
                isHiddenNav = carousel.isHiddenNav,
                NumberOfItems = carousel.NumberOfItems,
                ItemMinWidth = carousel.ItemMinWidth,
                ItemMargin = carousel.ItemMargin,
                IsAutoRotate = carousel.IsAutoRotate,
                AutoRotate = carousel.AutoRotate,
            };

            var productIds = carousel.CarouselEntities.Where(x => x.Published).OrderBy(x => x.DisplayOrder).Select(x => x.EntityId).ToArray(); 
            var products = _productService.GetProductsByIds(productIds);
            ////ACL and store mapping
            //products = products.Where(p => _aclService.Authorize(p) && _storeMappingService.Authorize(p)).ToList();
            
            //if (products.Count == 0)
            //    return Content("");

            carouselModel.Products  = PrepareProductOverviewModels(products, true, true, null).ToList();

            return carouselModel;
        }

        [NonAction]
        protected CarouselEntityModel PrepareCarouselEntityModelForList(CarouselEntity carouselEntity)
        {
            var defaultProductPicture = _pictureService.GetPicturesByProductId(carouselEntity.EntityId, 1).FirstOrDefault();
            var carouselEntityModel = new CarouselEntityModel()
            {
                CarouselId = carouselEntity.CarouselId,
                Id = carouselEntity.Id,
                DisplayOrder = carouselEntity.DisplayOrder,
                EntityId = carouselEntity.EntityId,
                EntityName  = carouselEntity.EntityName,
                Published  = carouselEntity.Published,
                PictureThumbnailUrl = _pictureService.GetPictureUrl(defaultProductPicture, 75, true),
                ProductName = _productService.GetProductById(carouselEntity.EntityId).Name,
            };
            return carouselEntityModel;
        }

        [NonAction]
        protected virtual IEnumerable<ProductOverviewModel> PrepareProductOverviewModels(IEnumerable<Product> products,
            bool preparePriceModel = true, bool preparePictureModel = true,
            int? productThumbPictureSize = null, bool prepareSpecificationAttributes = false,
            bool forceRedirectionAfterAddingToCart = false)
        {
            return this.PrepareProductOverviewModels(_workContext,
                _storeContext, _categoryService, _productService, _specificationAttributeService,
                _priceCalculationService, _priceFormatter, _permissionService,
                _localizationService, _taxService, _currencyService,
                _pictureService, _webHelper, _cacheManager,
                _catalogSettings, _mediaSettings, products,
                preparePriceModel, preparePictureModel,
                productThumbPictureSize, prepareSpecificationAttributes,
                forceRedirectionAfterAddingToCart);
        }

        #endregion

        #region Public

        [AdminAuthorize]
        [ChildActionOnly]
        public ActionResult Configure()
        {
            return View("~/Plugins/Widgets.Carousel/Views/Configure.cshtml");
        }

        [ChildActionOnly]
        public ActionResult PublicInfo(string widgetZone)
        {
            ViewBag.widgetZone = widgetZone;
            return View("~/Plugins/Widgets.Carousel/Views/PublicInfo.cshtml");
        }

        [HttpPost]
        [ValidateInput(false)]
        public ActionResult Carousels(string var1 = "", string var2 = "") //var1 isMetar
        {
            var carousels = _carouselService.GetCarouselsByWidgetZones(var1);
            var model = new CarouselListModel();
            foreach (var c in carousels)
            {
                model.AvailableCarousels.Add(PrepareCarouselModel(c));
            }

            return Json(new
            {
                html = this.RenderPartialViewToString("~/Plugins/Widgets.Carousel/Views/Carousels.cshtml", model),
            });
        }
        #endregion

       #region Admin
        #region List

        public ActionResult Index()
        {
            return RedirectToAction("List");
        }

        public ActionResult List()
        {
            var model = new CarouselListModel();

            return View("~/Plugins/Widgets.Carousel/Views/List.cshtml", model);
        }

        [HttpPost]
        public ActionResult List(DataSourceRequest command, CarouselListModel model)
        {
            var carousels = _carouselService.GetAllCarousels(model.SearchCarouselName,
                 command.Page - 1, command.PageSize);

            var tmp = new List<CarouselModel>();
            foreach (var carousel in carousels)
                tmp.Add(PrepareCarouselModel(carousel));

            var tmp2 = tmp.PagedForCommand(command);
            var gridModel = new DataSourceResult
            {
                Data = tmp2,
                Total = tmp2.Count()
            };

            return new JsonResult
            {
                Data = gridModel
            };
        }

       #endregion

       #region Create / Edit / Delete

        public ActionResult Create()
        {
            var model = new CarouselModel();
            model.Published = true;
            model.CustomProductBox = false;
            model.isHiddenNav = true;
            model.NumberOfItems = 4;
            model.ItemMinWidth = 200;
            model.ItemMargin = 20;
            model.IsAutoRotate = true;
            model.AutoRotate = 4000;

            return View("~/Plugins/Widgets.Carousel/Views/Create.cshtml", model);
        }

        [HttpPost, ParameterBasedOnFormName("save-continue", "continueEditing")]
        public ActionResult Create(CarouselModel model, bool continueEditing)
        {
            if (ModelState.IsValid)
            {
                var carousel = new CarouselObject()
                {
                    Id = model.Id,
                    Name = model.Name,
                    WidgetZone = model.WidgetZone,
                    Published = model.Published,
                    DisplayOrder = model.DisplayOrder,
                    CustomProductBox = model.CustomProductBox,
                    isHiddenNav = model.isHiddenNav,
                    NumberOfItems = model.NumberOfItems,
                    ItemMinWidth = model.ItemMinWidth,
                    ItemMargin = model.ItemMargin,
                    IsAutoRotate = model.IsAutoRotate,
                    AutoRotate = model.AutoRotate,
                };
                _carouselService.InsertCarousel(carousel);

                SuccessNotification(_localizationService.GetResource("Plugins.Widgets.Carousel.Added"));
                return continueEditing ? RedirectToAction("Edit", new { id = carousel.Id }) : RedirectToAction("List");
            }

            return View(model);
        }

        public ActionResult Edit(int id)
        {
            var carousel = _carouselService.GetCarouselById(id);
            if (carousel == null)
                //No page found with the specified id
                return RedirectToAction("List");
            var model = PrepareCarouselModel(carousel);

            return View("~/Plugins/Widgets.Carousel/Views/Edit.cshtml", model);
        }

        [HttpPost, ParameterBasedOnFormName("save-continue", "continueEditing")]
        public ActionResult Edit(CarouselModel model, bool continueEditing)
        {
            var carousel = _carouselService.GetCarouselById(model.Id);
            if (carousel == null)
                //No page found with the specified id
                return RedirectToAction("List");

            if (ModelState.IsValid)
            {
                carousel.Name = model.Name;
                carousel.WidgetZone = model.WidgetZone;
                carousel.Published = model.Published;
                carousel.DisplayOrder = model.DisplayOrder;
                carousel.CustomProductBox = model.CustomProductBox;
                carousel.isHiddenNav = model.isHiddenNav;
                carousel.NumberOfItems = model.NumberOfItems;
                carousel.ItemMinWidth = model.ItemMinWidth;
                carousel.ItemMargin = model.ItemMargin;
                carousel.IsAutoRotate = model.IsAutoRotate;
                carousel.AutoRotate = model.AutoRotate;

                _carouselService.UpdateCarousel(carousel);

                SuccessNotification(_localizationService.GetResource("Plugins.Widgets.Carousel.Updated"));
                return continueEditing ? RedirectToAction("Edit", carousel.Id) : RedirectToAction("List");
            }

            return View(model);
        }

        [HttpPost]
        public ActionResult Delete(int id)
        {
            var carousel = _carouselService.GetCarouselById(id);
            if (carousel == null)
                //No page found with the specified id
                return RedirectToAction("List");

            _carouselService.DeleteCarousel(carousel);

            SuccessNotification(_localizationService.GetResource("Plugins.Widgets.Carousel.Deleted"));
            return RedirectToAction("List");
        }

       #endregion

        #region Carousel Entity

        [HttpPost]
        public ActionResult CarouselEntitySelect(int carouselId, DataSourceRequest command)
        {
            var carousel = _carouselService.GetCarouselById(carouselId);
            if (carousel == null)
                throw new ArgumentException("No carousel found with the specified id", "carouselId");

            var entities = carousel.CarouselEntities.OrderByDescending(sp => sp.DisplayOrder).ThenByDescending(sp => sp.Id).ToList();
            var gridModel = new DataSourceResult
            {
                Data = entities.Select(PrepareCarouselEntityModelForList),
                Total = entities.Count
            };
            return new JsonResult
            {
                Data = gridModel
            };
        }

        [HttpPost]
        public ActionResult CarouselEntityDelete(int id)
        {
            var carouselentity = _carouselService.GetCarouselEntityById(id);
            if (carouselentity == null)
                throw new ArgumentException("No carousel entity found with the specified id");

            _carouselService.DeleteCarouselEntity(carouselentity);


            return Json(null);
        }

        [HttpPost]
        public ActionResult CarouselEntityUpdate([Bind(Exclude = "ConfigurationRouteValues")] CarouselEntityModel model)
        {
            var carouselEntity = _carouselService.GetCarouselEntityById(model.Id);
            
            carouselEntity.Published = model.Published;
            carouselEntity.DisplayOrder = model.DisplayOrder;
            _carouselService.UpdateCarouselEntity(carouselEntity);
            
            return new NullJsonResult();
        }

        public ActionResult ProductAddPopup(int carouselId)
        {
            var model = new AddCarouselProductModel();
            //categories
            model.AvailableCategories.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });
            var categories = _categoryService.GetAllCategories(showHidden: true);
            foreach (var c in categories)
                model.AvailableCategories.Add(new SelectListItem() { Text = c.GetFormattedBreadCrumb(categories), Value = c.Id.ToString() });

            //manufacturers
            model.AvailableManufacturers.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });
            foreach (var m in _manufacturerService.GetAllManufacturers(showHidden: true))
                model.AvailableManufacturers.Add(new SelectListItem() { Text = m.Name, Value = m.Id.ToString() });

            //stores
            model.AvailableStores.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });
            foreach (var s in _storeService.GetAllStores())
                model.AvailableStores.Add(new SelectListItem() { Text = s.Name, Value = s.Id.ToString() });

            //vendors
            model.AvailableVendors.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });
            foreach (var v in _vendorService.GetAllVendors(showHidden: true))
                model.AvailableVendors.Add(new SelectListItem() { Text = v.Name, Value = v.Id.ToString() });

            //product types
            model.AvailableProductTypes = ProductType.SimpleProduct.ToSelectList(false).ToList();
            model.AvailableProductTypes.Insert(0, new SelectListItem() { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });

            return View("~/Plugins/Widgets.Carousel/Views/ProductAddPopup.cshtml", model);
        }

        [HttpPost]
        public ActionResult ProductAddPopupList(DataSourceRequest command, AddCarouselProductModel model)
        {
            var gridModel = new DataSourceResult();
            var products = _productService.SearchProducts(
                categoryIds: new List<int>() { model.SearchCategoryId },
                manufacturerId: model.SearchManufacturerId,
                storeId: model.SearchStoreId,
                vendorId: model.SearchVendorId,
                productType: model.SearchProductTypeId > 0 ? (ProductType?)model.SearchProductTypeId : null,
                keywords: model.SearchProductName,
                pageIndex: command.Page - 1,
                pageSize: command.PageSize,
                showHidden: true
                );
            gridModel.Data = products.Select(x => x.ToModel());
            gridModel.Total = products.TotalCount;

            return Json(gridModel);
        }

        [HttpPost]
        [FormValueRequired("save")]
        public ActionResult ProductAddPopup(string btnId, string formId, AddCarouselProductModel model)
        {
            if (model.SelectedProductIds != null)
            {
                foreach (int id in model.SelectedProductIds)
                {
                    var product = _productService.GetProductById(id);
                    if (product != null)
                    {
                        int pictureId = 0;
                        var pictureList = _productService.GetProductPicturesByProductId(product.Id);
                        if (pictureList != null && pictureList.Count > 0)
                            pictureId = pictureList.FirstOrDefault().PictureId;

                        _carouselService.SaveCarouselEntity(product, model.CarouselId);
                    }
                }
            }

            ViewBag.RefreshPage = true;
            ViewBag.btnId = btnId;
            ViewBag.formId = formId;
            return View("~/Plugins/Widgets.Carousel/Views/ProductAddPopup.cshtml", model);
        }
        #endregion
        #endregion
    }
}